Spring에서 Configuration과 Configurable 어노테이션의 차이

Problem

지난번 JDBC Test는 직접 만든 빈들이 추가되지 않기 때문에 직접 빈을 주입해주는 방식을 사용해야한다는 것을 알아냈다.

이번에는 여러 빈을 추가해야했기 때문에 GameTestConfiguration 클래스를 직접 아래처럼 만들었고, JDBC Test에 @Import를 사용해 주입해주었다.

@Configuration
public class GameTestConfiguration {  
    @Autowired  
    private JdbcTemplate jdbcTemplate;  
    @Bean  
    public GameDAO racingCarGameDAO() {  
        final RacingCarDAO racingCarDAO = new RacingCarDAO(this.jdbcTemplate);  
        return new RacingCarGameDAO(this.jdbcTemplate, racingCarDAO);  
    }  
}

이렇게 하면 JDBC 테스트는 정상적으로 돌아갔다. 하지만, Controller 테스트를 위해 SpringBoot Test를 돌리면 아래와 같은 예외가 발생했다.

Failed to load ApplicationContext
java.lang.IllegalStateException: Failed to load ApplicationContext

자세한 설명으로는 GameTestConfiguration에서 등록해주었던 racingCarGameDAO가 중복된다는 것이였다.

Reason

이유는 @Configuration@Configurable의 차이에 있었다.

@Configuration 어노테이션은 클래스를 구성 클래스로 표시하는 데 사용된다. @Configuration 클래스의 목적은 Spring 컨테이너에 대한 빈 정의를 정의하는 것이다.

반대로 @Configurable 어노테이션은 Spring 컨테이너에 의해 관리되지 않는 빈들을 주입해줄 수 있는 설정 클래스를 표시한다.

다시 한 번 코드를 보면 @Configuration이 붙어있는 것을 알 수 있다.

@Configuration
public class GameTestConfiguration

따라서 SpringBootTest를 실행하게 되면 GameTestConfiguration에 의해 스프링 컨테이너에 racingCarGameDAO 빈이 등록되고, @Repository 어노테이션이 붙은 RacingCarGameDAO 또한 빈에 등록되므로 중복이 되어 예외가 발생한다.

Solution

@Configuration 대신 @Configurable 어노테이션을 붙여서 해결 가능하다.